﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;

using ChiDao.Component.Utils;
using ChiDao.Business.Models;
using ChiDao.Business.Models.FlowProcessNew;
using ChiDao.Site.Models;
using ChiDao.Business.Data.Repositories.FlowProcessNew;
using System.Collections;
using System.Xml;


namespace ChiDao.Business.Service.Impl
{
    [Export(typeof(IProcessUtilsService))]
    public class ProcessUtilsService : IProcessUtilsService
    {
        [Import]
        protected IHolidayRequestRepository HolidayRequestRepository { get; set; }
        [Import]
        protected IBaklogTaskNewRepository BaklogTaskNewRepository { get; set; }
        [Import]
        protected IProcessNewRepository ProcessNewRepository { get; set; }
        [Import]
        protected IProcessNodeNewRepository ProcessNodeNewRepository { get; set; }
        [Import]
        protected IProcessedTaskRepository ProcessedTaskRepository { get; set; }
        [Import]
        protected IFlowProcessGraphRepository FlowProcessGraphRepository { get; set; }

        public object ExecuteCommand(string command, System.Collections.Hashtable paraList)
        {
            object result = null;
            switch (command)
            {
                case "GetNodeForHolidayRequest":
                    result = GetNodeForHolidayRequest(paraList);
                    break;
                case "GetProcessPersonForHolidayRequest":
                    result = GetProcessPersonForHolidayRequest(paraList);
                    break;
            }
            return result;
        }

        private string GetNodeForHolidayRequest(Hashtable para)
        {
            Guid queryID = Guid.Parse(para["ProcessID"].ToString());
            IQueryable<HolidayRequest> holidayRequests = HolidayRequestRepository.Entities.Where(h => h.ID == queryID);
            HolidayRequest holidayRequest = holidayRequests.First();
            int timeSpan = (holidayRequest.RequestEndDate - holidayRequest.RequestStartDate).Days + 1;
            if (timeSpan >= 5)
            {
                return "ManagerApproved";
            }
            else
            {
                return "LeaderApproved";
            }
        }

        private string GetProcessPersonForHolidayRequest(Hashtable para)
        {
            if (para["param1"].ToString() == "true")
            {
                return "lis,wangw";
            }
            else
            {
                return "chenl,northow";
            }
        }



        public bool BackRequest(string processCode, string processID, string requestPerson)
        {
            IQueryable<BaklogTaskNew> baklogTaskNews = BaklogTaskNewRepository.Entities.Where(c => c.ProcessID == processID);
            string currentProcessNodeCode = baklogTaskNews.First().CurrentProcessNodeCode;
            string currentProcessPerson = baklogTaskNews.First().CurrentProcessPerson;

            ProcessNew processNew = ProcessNewRepository.Entities.Where(p => p.ProcessCode == processCode).First();
            ProcessNodeNew currentProcessNode = ProcessNodeNewRepository.Entities.Where(p => p.PID == processNew.ID && p.NodeCode == currentProcessNodeCode).First();

            List<ProcessNodeNew> passNodeList = new List<ProcessNodeNew>();
            bool isRequestNode = false;
            ProcessNodeNew backProcessNode = GetBackNodeCode(currentProcessNode.NodeXML, processID, processNew.ID, passNodeList, ref isRequestNode);

            List<Guid> idList = new List<Guid>();
            foreach (BaklogTaskNew baklogTaskNew in baklogTaskNews)
            {
                idList.Add(baklogTaskNew.ID);
            }
            foreach (Guid id in idList)
            {
                BaklogTaskNewRepository.Delete(id);
            }

            ProcessedTask processedTask = new ProcessedTask()
            {
                ID = Guid.NewGuid(),
                ProcessID = processID,
                CurrentProcessNodeCode = currentProcessNode.NodeCode,
                CurrentProcessNodeName = currentProcessNode.NodeName,
                ApprovalOpinion = "回退",
                CurrentProcessPerson = currentProcessPerson,
                ProcessTime = DateTime.Now,
                HandleState = "4"
            };
            ProcessedTaskRepository.Insert(processedTask);

            //FlowProcessGraph flowProcessGraph = new FlowProcessGraph()
            //{
            //    ID = Guid.NewGuid(),
            //    ProcessID = processID,
            //    PassProcessNodeCode = currentProcessNode.NodeCode,
            //    PassProcessNodeType = "4"
            //};
            //FlowProcessGraphRepository.Insert(flowProcessGraph);
            foreach (ProcessNodeNew processNodeNew in passNodeList)
            {
                FlowProcessGraph addFlowProcessGraph = new FlowProcessGraph()
                {
                    ID = Guid.NewGuid(),
                    ProcessID = processID,
                    PassProcessNodeCode = processNodeNew.NodeCode,
                    PassProcessNodeType = "4"
                };
                FlowProcessGraphRepository.Insert(addFlowProcessGraph);
            }
            //if (isRequestNode)
            //{
            FlowProcessGraph flowProcessGraph = new FlowProcessGraph()
            {
                ID = Guid.NewGuid(),
                ProcessID = processID,
                PassProcessNodeCode = backProcessNode.NodeCode,
                PassProcessNodeType = "4"
            };
            FlowProcessGraphRepository.Insert(flowProcessGraph);
            //}

            if (!isRequestNode && !string.IsNullOrEmpty(backProcessNode.NodeXML))
            {
                string processPersonStr = string.Empty;
                XmlDocument docPerson = new XmlDocument();
                docPerson.LoadXml(backProcessNode.NodeXML);
                XmlNodeList personNodeList = docPerson.SelectNodes("NodeXML/defaultProcessPerson");
                string getType = personNodeList[0].SelectSingleNode("getType").InnerText;
                if (getType == "value")
                {
                    processPersonStr = personNodeList[0].SelectSingleNode("presonList").InnerText;
                }
                else
                {
                    string functionName = personNodeList[0].SelectSingleNode("functionName").InnerText;
                    XmlNode paraNode = personNodeList[0].SelectSingleNode("functionParam");
                    Hashtable para = new Hashtable();
                    para.Add("ProcessID", processID);
                    if (paraNode != null && paraNode.ChildNodes.Count > 0)
                    {
                        foreach (XmlNode node in paraNode.ChildNodes)
                        {
                            para.Add(node.Name, node.InnerText);
                        }
                    }
                    processPersonStr = ExecuteCommand(functionName, para) as string;
                }
                string[] processPersonArr = processPersonStr.Split(',');
                foreach (string processPerson in processPersonArr)
                {
                    BaklogTaskNew add = new BaklogTaskNew();
                    add.ID = GuidHelper.NewGuid();
                    add.ProcessID = processID;
                    switch (processCode)
                    {
                        case "HolidayRequest":
                            add.TaskName = "请假单";
                            break;
                    }
                    add.TaskType = processCode;
                    add.RequestPerson = requestPerson;
                    add.CurrentProcessNodeCode = backProcessNode.NodeCode;
                    add.CurrentProcessPerson = processPerson;
                    BaklogTaskNewRepository.Insert(add);
                }
            }

            return isRequestNode;
        }

        private ProcessNodeNew GetBackNodeCode(string nodeXML, string processID, Guid pid, List<ProcessNodeNew> passNodeList, ref bool isRequestNode)
        {
            XmlDocument docBackNode = new XmlDocument();
            docBackNode.LoadXml(nodeXML);
            XmlNode backCellNode = docBackNode.SelectSingleNode("NodeXML/backCell");
            XmlNode getTypeNode = backCellNode.SelectSingleNode("getType");
            string backNodeCode = string.Empty;
            if (getTypeNode.InnerText == "value")
            {
                backNodeCode = backCellNode.SelectSingleNode("backCellName").InnerText;
            }
            else
            {
                string functionName = backCellNode.SelectSingleNode("functionName").InnerText;
                XmlNode paraNode = backCellNode.SelectSingleNode("functionParam");
                Hashtable para = new Hashtable();
                para.Add("ProcessID", processID);
                if (paraNode != null && paraNode.ChildNodes.Count > 0)
                {
                    foreach (XmlNode node in paraNode.ChildNodes)
                    {
                        para.Add(node.Name, node.InnerText);
                    }
                }
                backNodeCode = ExecuteCommand(functionName, para) as string;
            }
            ProcessNodeNew backProcessNode = ProcessNodeNewRepository.Entities.Where(p => p.PID == pid && p.NodeCode == backNodeCode).First();
            if (backProcessNode.NodeType == "1")
            {
                passNodeList.Add(backProcessNode);
                return GetBackNodeCode(backProcessNode.NodeXML, processID, pid, passNodeList, ref isRequestNode);
            }
            else
            {
                if (backProcessNode.NodeType == "0")
                {
                    isRequestNode = true;
                }
                return backProcessNode;
            }
        }

        public void CancelRequest(string processCode, string processID)
        {
            IQueryable<BaklogTaskNew> baklogTaskNews = BaklogTaskNewRepository.Entities.Where(c => c.ProcessID == processID);
            string currentProcessNodeCode = baklogTaskNews.First().CurrentProcessNodeCode;
            string currentProcessPerson = baklogTaskNews.First().CurrentProcessPerson;

            ProcessNew processNew = ProcessNewRepository.Entities.Where(p => p.ProcessCode == processCode).First();
            ProcessNodeNew currentProcessNode = ProcessNodeNewRepository.Entities.Where(p => p.PID == processNew.ID && p.NodeCode == currentProcessNodeCode).First();

            List<Guid> idList = new List<Guid>();
            foreach (BaklogTaskNew baklogTaskNew in baklogTaskNews)
            {
                idList.Add(baklogTaskNew.ID);
            }
            foreach (Guid id in idList)
            {
                BaklogTaskNewRepository.Delete(id);
            }

            ProcessedTask processedTask = new ProcessedTask()
            {
                ID = Guid.NewGuid(),
                ProcessID = processID,
                CurrentProcessNodeCode = currentProcessNode.NodeCode,
                CurrentProcessNodeName = currentProcessNode.NodeName,
                ApprovalOpinion = "终止",
                CurrentProcessPerson = currentProcessPerson,
                ProcessTime = DateTime.Now,
                HandleState = "3"
            };
            ProcessedTaskRepository.Insert(processedTask);

            FlowProcessGraph flowProcessGraph = new FlowProcessGraph()
            {
                ID = Guid.NewGuid(),
                ProcessID = processID,
                PassProcessNodeCode = currentProcessNode.NodeCode,
                PassProcessNodeType = "3"
            };
            FlowProcessGraphRepository.Insert(flowProcessGraph);
        }

        public WorkFlowNewView GenerateGraph(string processCode, string processID, string handleState)
        {
            #region 解析节点信息，添加所有的节点和连线，并设置申请节点之前和结束节点以及连线的颜色
            ProcessNew processNew = ProcessNewRepository.Entities.Where(p => p.ProcessCode == processCode).First();
            IQueryable<ProcessNodeNew> processNodeNewList = ProcessNodeNewRepository.Entities.Where(p => p.PID == processNew.ID).OrderBy(p => p.OrderNo);
            WorkFlowNewView workFlowNewView = new WorkFlowNewView();
            bool isPassRequestNode = false;
            bool isPassFinishNode = false;
            foreach (ProcessNodeNew processNodeNew in processNodeNewList)
            {
                if (!string.IsNullOrEmpty(processNodeNew.NodeType) && processNodeNew.NodeType == "0")
                {
                    isPassRequestNode = true;
                }
                WorkFlowNodeView workFlowNodeView = new WorkFlowNodeView();
                workFlowNodeView.NodeCode = processNodeNew.NodeCode;
                workFlowNodeView.NodeName = processNodeNew.NodeName;
                workFlowNodeView.NodeType = processNodeNew.NodeType;
                workFlowNodeView.LocationX = processNodeNew.LocationX;
                workFlowNodeView.LocationY = processNodeNew.LocationY;
                workFlowNodeView.Width = processNodeNew.Width;
                workFlowNodeView.Height = processNodeNew.Height;
                workFlowNodeView.Shape = processNodeNew.Shape;
                workFlowNodeView.NodeColor = "";
                if (!string.IsNullOrEmpty(handleState))
                {
                    //单据存在的时候，申请节点之前的节点为已通过
                    //如果单据完成，那么结束节点为已通过
                    if (!isPassRequestNode || isPassFinishNode)
                    {
                        workFlowNodeView.NodeColor = "fillColor=green;";
                    }
                }
                workFlowNewView.lstWorkFlowNodeView.Add(workFlowNodeView);

                if (!string.IsNullOrEmpty(processNodeNew.NodeType) && processNodeNew.NodeType == "2" && handleState == "2")
                {
                    isPassFinishNode = true;
                }
                if (!string.IsNullOrEmpty(processNodeNew.NodeXML))
                {
                    XmlDocument docNextNode = new XmlDocument();
                    docNextNode.LoadXml(processNodeNew.NodeXML);
                    XmlNode nextNode = docNextNode.SelectSingleNode("NodeXML/nextCell");
                    foreach (XmlNode node in nextNode.ChildNodes)
                    {
                        WorkFlowNodeLineView workFlowNodeLineView = new WorkFlowNodeLineView();
                        workFlowNodeLineView.NodeCode = processNodeNew.NodeCode;
                        workFlowNodeLineView.NextNodeCode = node.InnerText;
                        if (node.Attributes.Count == 1)
                        {
                            workFlowNodeLineView.LineTitle = node.Attributes[0].Value;
                        }
                        workFlowNodeLineView.LineColor = "";
                        if (!string.IsNullOrEmpty(handleState))
                        {
                            //单据存在的时候，申请节点之前的节点连线为已通过
                            //如果单据完成，那么结束节点为已通过
                            if (!isPassRequestNode || isPassFinishNode)
                            {
                                workFlowNodeLineView.LineColor = "strokeColor=green;";
                            }
                        }
                        workFlowNewView.lstWorkFlowNodeLineView.Add(workFlowNodeLineView);
                    }
                }
            }
            #endregion

            #region 设置节点和连线的颜色
            IQueryable<FlowProcessGraph> flowProcessGraphList = FlowProcessGraphRepository.Entities.Where(f => f.ProcessID == processID).OrderBy(f => f.AddDate);
            if (!string.IsNullOrEmpty(handleState))
            {
                //设置流转回退和终止的节点和连线的颜色
                foreach (FlowProcessGraph flowProcessGraph in flowProcessGraphList)
                {
                    WorkFlowNodeView workFlowNode = workFlowNewView.lstWorkFlowNodeView.Where(n => n.NodeCode == flowProcessGraph.PassProcessNodeCode).First();
                    workFlowNode.NodeColor = "fillColor=green;";
                    if (flowProcessGraph.PassProcessNodeType == "3")
                    {
                        workFlowNode.NodeColor = "fillColor=red;";
                    }

                    IQueryable<FlowProcessGraph> preFlowProcessGraphList = flowProcessGraphList.Where(f => f.AddDate < flowProcessGraph.AddDate).OrderByDescending(f => f.AddDate);
                    if (preFlowProcessGraphList.Count() > 0)
                    {
                        string currentNodeCode = preFlowProcessGraphList.First().PassProcessNodeCode;
                        IEnumerable<WorkFlowNodeLineView> workFlowNodeLineList = workFlowNewView.lstWorkFlowNodeLineView.Where(l => (l.NodeCode == currentNodeCode && l.NextNodeCode == flowProcessGraph.PassProcessNodeCode) || (l.NodeCode == flowProcessGraph.PassProcessNodeCode && l.NextNodeCode == currentNodeCode));
                        if (workFlowNodeLineList.Count() > 0)
                        {
                            WorkFlowNodeLineView workFlowNodeLine = workFlowNodeLineList.First();
                            workFlowNodeLine.LineColor = "strokeColor=green;";
                            if (flowProcessGraph.PassProcessNodeType == "4")
                            {
                                workFlowNodeLine.LineColor = "strokeColor=red;";
                            }
                        }
                    }
                }

                //设置当前节点颜色
                if (handleState == "0")
                {
                    WorkFlowNodeView workFlowNode = workFlowNewView.lstWorkFlowNodeView.Where(n => n.NodeType == "0").First();
                    workFlowNode.NodeColor = "fillColor=blue;";
                }
                else if (handleState == "1" || handleState == "4")
                {
                    BaklogTaskNew baklogTaskNew = BaklogTaskNewRepository.Entities.Where(c => c.ProcessID == processID).First();
                    WorkFlowNodeView workFlowNode = workFlowNewView.lstWorkFlowNodeView.Where(n => n.NodeCode == baklogTaskNew.CurrentProcessNodeCode).First();
                    workFlowNode.NodeColor = "fillColor=blue;";
                }
            }
            #endregion

            return workFlowNewView;
        }
    }
}